import json
import os
import requests
from PIL import Image
from io import BytesIO
import re
import time
import random

def extract_image_id(url):
    """从URL中提取图片ID"""
    match = re.search(r'/([^/]+)!', url)
    return match.group(1) if match else None

def download_and_convert_images(json_str):
    """从JSON字符串中提取图片URL，下载并转换为PNG格式"""
    # 创建一个Session对象来维持会话
    session = requests.Session()
    
    # 设置更完整的请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Accept': 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Accept-Encoding': 'gzip, deflate, br',
        'Connection': 'keep-alive',
        'Referer': 'https://www.xiaohongshu.com/',
        'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
        'Sec-Ch-Ua-Mobile': '?0',
        'Sec-Ch-Ua-Platform': '"Windows"',
        'Sec-Fetch-Dest': 'image',
        'Sec-Fetch-Mode': 'no-cors',
        'Sec-Fetch-Site': 'same-site',
        'Pragma': 'no-cache',
        'Cache-Control': 'no-cache',
    }
    
    session.headers.update(headers)

    # 确保sortpic目录存在
    if not os.path.exists('sortpic'):
        os.makedirs('sortpic')
        print("创建sortpic目录")

    try:
        # 解析JSON字符串
        json_str = '[' + json_str.strip().rstrip(',') + ']'
        data = json.loads(json_str)
        
        # 使用列表和集合来保持顺序并去重
        seen = set()
        urls = []
        first_url = None
        
        # 遍历所有项目
        for i, item in enumerate(data):
            url = item['src']
            if url not in seen:
                seen.add(url)
                if i == 0:  # 如果是第一个URL
                    first_url = url
                else:  # 其他URL正常添加到列表
                    urls.append(url)
        
        # 将第一个URL添加到列表末尾
        if first_url:
            urls.append(first_url)
        
        print(f"找到 {len(urls)} 个唯一的图片URL")

        # 下载和转换每个图片
        for i, url in enumerate(urls, 1):
            try:
                # 获取图片ID
                image_id = extract_image_id(url)
                if not image_id:
                    print(f"⚠️ 无法从URL提取图片ID: {url}")
                    continue

                # 下载图片
                print(f"正在下载图片 {i}/{len(urls)}: {url}")
                
                # 添加随机延迟，避免请求过快
                time.sleep(random.uniform(1, 3))
                
                # 使用session进行请求
                response = session.get(url, timeout=10)
                response.raise_for_status()

                # 使用PIL打开图片
                img = Image.open(BytesIO(response.content))

                # 保存为PNG格式
                output_path = os.path.join('sortpic', f"{image_id}.png")
                img.save(output_path, 'PNG')
                print(f"✅ 成功保存图片: {output_path}")

            except requests.RequestException as e:
                print(f"❌ 下载图片时出错: {str(e)}")
                if hasattr(e.response, 'status_code'):
                    print(f"状态码: {e.response.status_code}")
                    print(f"响应头: {e.response.headers}")
            except Exception as e:
                print(f"❌ 处理图片时出错: {str(e)}")

    except json.JSONDecodeError as e:
        print(f"❌ JSON解析错误: {str(e)}")
    except Exception as e:
        print(f"❌ 发生未预期的错误: {str(e)}")

def extract_urls(json_str):
    """从JSON字符串中提取图片URL"""
    try:
        # 解析JSON字符串
        json_str = '[' + json_str.strip().rstrip(',') + ']'
        data = json.loads(json_str)
        
        # 使用列表和集合来保持顺序并去重
        seen = set()
        urls = []
        first_url = None
        
        # 遍历所有项目
        for i, item in enumerate(data):
            url = item['src']
            if url not in seen:
                seen.add(url)
                if i == 0:  # 如果是第一个URL
                    first_url = url
                else:  # 其他URL正常添加到列表
                    urls.append(url)
        
        # 将第一个URL添加到列表末尾
        if first_url:
            urls.append(first_url)
        
        print(f"找到 {len(urls)} 个唯一的图片URL:")
        
        # 输出URL列表
        for url in urls:
            print(url)
            
    except json.JSONDecodeError as e:
        print(f"❌ JSON解析错误: {str(e)}")
    except Exception as e:
        print(f"❌ 发生未预期的错误: {str(e)}")

if __name__ == "__main__":
    print("请输入JSON数据（每个图片对象占一行，输入完成后按Ctrl+D或Ctrl+Z）：")
    json_input = """
{
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/f8b532cce62d37765ec2b08605f4eb7f/1040g2sg30t2km39q3u4g5o9j09f0jg7sivdsg0o!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/2c2be028bc683dc945b15868c5a4c7bb/1040g2sg30t2km39q3u605o9j09f0jg7sd8lb20g!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/a628d5317d3be2554043a99494c792dc/1040g2sg30t2km39q3u5g5o9j09f0jg7sqiurpjg!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/65317ae3857c53aceb87df753da7519b/1040g2sg30t2km39q3u405o9j09f0jg7sjs7me98!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/441ecb0dfc485b82e21bafddd5ff4ef0/1040g2sg30t2km39q3u2g5o9j09f0jg7si5fvo5g!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/de69f4f88f6a036ef4c0bf8dcdd86314/1040g2sg30t2km39q3u6g5o9j09f0jg7s4fj3mfg!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/2be7016ae18542681afb43862ea5ab37/1040g2sg30t2km39q3u3g5o9j09f0jg7s0ia44h8!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/a6ca6ce404853e09b14ff2fc87d5c4e5/1040g2sg30t2km39q3u305o9j09f0jg7s424gn40!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/c237ef8f459916a69a845532a288e7d2/1040g2sg30t2km39q3u205o9j09f0jg7sj4c9ksg!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/2a94cd8e39691db03d7e05552723286e/1040g2sg30t2km39q3u505o9j09f0jg7sgc6o7h0!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/77f14bf61049fbcae1e5f4345e032a0a/1040g2sg30t2km39q3u105o9j09f0jg7sctae7s8!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/f8b532cce62d37765ec2b08605f4eb7f/1040g2sg30t2km39q3u4g5o9j09f0jg7sivdsg0o!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
        {
            "src": "https://sns-webpic-qc.xhscdn.com/202502142331/2c2be028bc683dc945b15868c5a4c7bb/1040g2sg30t2km39q3u605o9j09f0jg7sd8lb20g!nd_dft_wlteh_webp_3",
            "alt": "",
            "width": 780,
            "height": 390
        },
    """
    extract_urls(json_input) 